package com.alifi.crm.dal;

import java.lang.reflect.ParameterizedType;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.springframework.orm.ibatis.SqlMapClientCallback;
import org.springframework.orm.ibatis.SqlMapClientTemplate;

import com.ibatis.sqlmap.client.SqlMapExecutor;

/**
 * CRUD dao ibatis实现
 * 
 * @author wb_haichun.panhch
 * 
 * @param <E>
 * @param <ID>
 */
public class IbatisCRUDDAO<E extends BaseDO>
		implements CRUDDAO<E> {

	@Resource(name = "sqlMapClientTemplate")
	private SqlMapClientTemplate sqlMapClientTemplate;

    
	/** 批量删除 */
	protected static final String BATCH_DELETE = "batchDelete";

	/** 统计数量 */
	protected static final String COUNT = "count";

	/** 删除 */
	protected static final String DELETE = "delete";

	/** 查找 */
	protected static final String FIND = "find";

	/** 读取 */
	protected static final String GET = "get";

	/** 插入数据 */
	protected static final String INSERT = "insert";

	/** 更新 */
	protected static final String UPDATE = "update";

	/** namepsace 默认取实体类名全路径 */
	private String namespace = ((Class<?>) ((ParameterizedType) getClass()
			.getGenericSuperclass()).getActualTypeArguments()[0]).getName();


    protected SqlMapClientTemplate getSqlMapClientTemplate() {
		return sqlMapClientTemplate;
	}

    public void setSqlMapClientTemplate(SqlMapClientTemplate sqlMapClientTemplate) {
        this.sqlMapClientTemplate = sqlMapClientTemplate;
    }

   
	/**
	 * ibatis namespace
	 * 
	 * <br>
	 * 子类可选择覆盖此方法使用自己的namespace
	 * 
	 * @return
	 */
	protected String getNamespace() {
		return namespace;
	}

	/**
	 * 生成statement名字
	 * 
	 * <br>
	 * 将namepace跟statement短语拼接组成完整的statement
	 * 
	 * @param stmt
	 *            statement短语
	 * @return namespace.stmt
	 */
	protected String genStmt(String stmt) {
		return getNamespace() + "." + stmt;
	}

	@SuppressWarnings("unchecked")
	@Override
	public void save(E entity) {
		Long id = (Long) getSqlMapClientTemplate().insert(genStmt(INSERT), entity);
		if (id != null) {
			entity.setId(id);
		}
	}

	@Override
	public void save(E[] entities) {
		save(Arrays.asList(entities));
	}

	@Override
	public void save(final Collection<E> entities) {
		// 此处本应该使用batch操作，但是经测试使用batch时不能返回主键id，因此逐个调用save
		for (E entity : entities) {
			save(entity);
		}
	}

	@Override
	public void update(E entity) {
		getSqlMapClientTemplate().update(genStmt(UPDATE), entity);
	}

	@Override
	public void update(E[] entities) {
		update(Arrays.asList(entities));
	}

	@Override
	public void update(final Collection<E> entities) {
		getSqlMapClientTemplate().execute(new SqlMapClientCallback() {
			@Override
			public Object doInSqlMapClient(SqlMapExecutor executor)
					throws SQLException {
				executor.startBatch();
				for (E entity : entities) {
					executor.update(genStmt(UPDATE), entity);
				}
				executor.executeBatch();
				return null;
			}
		});
	}


	@SuppressWarnings("unchecked")
	@Override
	public E get(Long id) {
		return (E) getSqlMapClientTemplate().queryForObject(genStmt(GET), id);
	}

	@Override
	public int count(Map<String, Object> params) {
		return ((Number) getSqlMapClientTemplate().queryForObject(
				genStmt(COUNT), params)).intValue();
	}

	@Override
	public List<E> find(Map<String, Object> params, int start, int count) {
		Map<String, Object> paramMap = (params == null) ? new HashMap<String, Object>()	: params;
		paramMap.put("start", start);
		paramMap.put("end", start + count);
		return find(paramMap);
	}

	@SuppressWarnings("unchecked")
	protected List<E> find(Map<String, Object> params) {
		return (List<E>) getSqlMapClientTemplate().queryForList(genStmt(FIND), params);
	}

}
